/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fresher.vng.controller;

import fresher.vng.model.UserModel;
import hapax.Template;
import hapax.TemplateDataDictionary;
import hapax.TemplateDictionary;
import hapax.TemplateException;
import hapax.TemplateLoader;
import hapax.TemplateResourceLoader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author quangtm5
 */
public class ChatController extends HttpServlet{
    
    private static final Logger logger = LoggerFactory.getLogger(ChatController.class.getName());
    
    private static final String URL_INDEX = "/index";
    private static final String URL_CHAT = "/chat";
    private static final String URL_POLL = "/poll";
    private static final String URL_JOIN = "/join";
        
    Map<String, UserModel> chatRoom = new HashMap<String,UserModel>();
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        
        String requestURI = req.getRequestURI();
        
        String userName = req.getParameter("userName");
        
        switch(requestURI)
        {
            case URL_INDEX:
            {
                resp.setContentType("text/html");
                
                resp.setStatus(HttpServletResponse.SC_OK);

                TemplateLoader templateLoader = new TemplateResourceLoader("fresher/");

                Template template = null;
                try 
                {
                    template = templateLoader.getTemplate("vng/view/index.xtm");
                } catch (TemplateException ex) {
                    logger.error(ex.getMessage(), ex);
                }
                
                TemplateDataDictionary dictionary = TemplateDictionary.create();
                
                String content = "";
                
                try       
                {
                    content = template.renderToString(dictionary);
                }
                catch (TemplateException ex)
                {
                    logger.error(ChatController.class.getName(), null, ex);
                }
                
                resp.getWriter().println(content);
                break;
            }
                
            case URL_JOIN:
            {
                //user want to join in chat room.
                join(req, resp);
                
                break;
            }
                
            case URL_CHAT:
            {
                //user want to send a message
                if(!userName.equals(""))
                {
                    chat(req, resp);
                }
                
                break;
            }
            case URL_POLL:
            {
                //user want to receive new message
                //return new message (if exist)
                //or wait until have a message 
                //or send nothing if timeout
                if(!userName.equals(""))
                {
                    poll(req, resp);
                }
                                             
                break;
            }
        }
        
        
    }
    
    public void join(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        String name = request.getParameter("userName");
        String nameOfReceiver = request.getParameter("userNameOfReceiver");
                
        logger.info("Join request - " + name);

        UserModel user = chatRoom.get(name);

        response.setContentType("text/json;charset=utf-8");

        //check if user's name has been existed
        if(user == null)
        {
            //create a new user
            user = new UserModel(name);
            //add a name of receiver
            user.getNameOfReceiver().add(nameOfReceiver);

            chatRoom.put(name, user);

            response.getWriter().print("{\"status\":\"success\"}");
        }
        else
        {
            //==do something with existed user
            response.getWriter().print("{\"status\":\"success\"}");
        }
    }
    
    public void chat(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        
        String userName = request.getParameter("userName");
        String nameOfReceiver = request.getParameter("userNameOfReceiver");
        String message = request.getParameter("message");
        logger.info("Chat request - " + userName + " - " + message);
        
        String storeMessage = userName + " : " + message;
        
        UserModel user = chatRoom.get(userName);
        
        if(user != null)
        {
            //send message to user in chat room
            for(UserModel mem:chatRoom.values())
            {
                if(mem.getNameOfAuthor().equals(nameOfReceiver))
                {
                    synchronized(mem)
                    {
                        mem.getMessage().add(storeMessage);

                        //if this member of room is polling now
                        if(mem.getContinuation() != null)
                        {
                            //resume the request 
                            //this line will resume poll request
                            mem.getContinuation().resume();

                            //set null again to perpair a new polling request
                            mem.setContinuation(null);
                        }
                    }
                }
            }
        }
        
        //response to client that server have received it's message
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().print("{\"status\": \"success\"}");
    }
    
    public void poll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        String userName = request.getParameter("userName");
        UserModel user = chatRoom.get(userName);
        logger.info("Poll request - " + userName);
        
        if(user != null)
        {
            synchronized(user)
            {
                if(user.getMessage().size() > 0)
                {
                    //send back one message
                    //take it out of the queue message
                    String message = user.getMessage().poll();

                    response.setContentType("text/json;charset=utf-8");
                    response.getWriter().print("{\"message\": \"" + message + "\"}");
                }
                else
                {
                    //if don't have any message yet
                    //wait (only for this request)
                    Continuation continuation = ContinuationSupport.getContinuation(request);

                    //first time, isInitial() return true
                    //when you set something in continuation, it will return false
                    if(continuation.isInitial())
                    {
                        //No chat message in queue so wait for timeout 
                        //or someone will send a message later
                        continuation.setTimeout(20000);//we will wait in 20s or until resume() is called
                                                       //if 20s is over, this request will be called again

                        continuation.suspend();//give this thread back to ThreadPool of server

                        user.setContinuation(continuation);
                    }
                    else
                    {
                        //when the time we wait in continuation property is over
                        //server will pick the request in timer queue to run again
                        //if request reach this line of code 
                        //Timeout => send a flag to check
                        response.setContentType("text/json;charset=utf-8");
                        response.getWriter().print("{\"message\": \"TIMEOUT: you don't have any message now\"}");
                    }
                }
            }
        }
    }
    
    
}
